package structure;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

import utilities.rle2dUtilities;

public class RLEPCXBuffer {
	private final static int MAX_BUFFER_LEN = 64;
	
	private int[] map;
	private int[] probability;
	
	private Queue<Integer> buffer;
	private ArrayList<Byte> returnSeq;
	private int count;
	
	private int prevColor = -1;
	private int seriesLen = 1;
	
	public RLEPCXBuffer() {
		
		map = new int[256];
		probability = new int[256];
		
		returnSeq = new ArrayList<Byte>();
		buffer = new LinkedList<Integer>();
	}
	
	public void evalProbability(String COLOR_NAME,ImageContainer ic,byte[][] bitmap){
		for(int i=0;i<ic.getHeigth();i++) {
			for(int j=0;j<ic.getWidth();j++) {
				if(bitmap[i][j] == 0) {
					if(rle2dUtilities.RED_NAME.equals(COLOR_NAME)) {
						probability[ic.getRedAt(j, i)]++;
					} else if(rle2dUtilities.GREEN_NAME.equals(COLOR_NAME)) {
						probability[ic.getGreenAt(j, i)]++;
					} else if(rle2dUtilities.BLUE_NAME.equals(COLOR_NAME)) {
						probability[ic.getBlueAt(j, i)]++;
					}
				}
			}
		}
		createMapping();
	}
	
	public void createMapping() {
		int [] temp = probability.clone();
		for(int i=0;i<map.length;i++) {
			int max = -1;
			int maxIndx = -1;
			for(int j=0;j<temp.length;j++) {
				if(max<temp[j]) {
					max = temp[j];
					maxIndx = j;
				}
			}
			map[maxIndx] = i;
			temp[maxIndx] = -1;
		}
	}
	

	public int[] getMap() {
		return map;
	}

	public int[] getProbability() {
		return probability;
	}
	
	public int getMapValue(int val) {
		return map[val];
	}

	
	public ArrayList<Byte> getReturnSeq() {
		return returnSeq;
	}

	public void addValue(Integer value) {	
		if(buffer.size()>=MAX_BUFFER_LEN) {
			rlepcx();
		}
		buffer.add(value);
		
	}
	
	public void rlepcx(){
		int color;
		if(!buffer.isEmpty()){
			int val = buffer.remove();
			if (val != -1){
				color = getMapValue(val);
			}
			else
				color = -1;
			if(color == prevColor){
				if(seriesLen >= rle2dUtilities.RLE_PCX_MAX_LEN) {
					returnSeq.add((byte)(rle2dUtilities.RLE_PCX_TRESHOLD+seriesLen));
					returnSeq.add((byte) prevColor);
					seriesLen = 1;
				} else {
					seriesLen++;
				}
			}
			else {
				if(seriesLen>1){
					returnSeq.add((byte)(rle2dUtilities.RLE_PCX_TRESHOLD+seriesLen));
					returnSeq.add((byte)prevColor);
				} else {
					if(prevColor!=-1) {
						if(prevColor>=rle2dUtilities.RLE_PCX_TRESHOLD) {
							returnSeq.add((byte)(rle2dUtilities.RLE_PCX_TRESHOLD+1));
							returnSeq.add((byte)prevColor);
						} else {
							returnSeq.add((byte)prevColor);
						}
					}
				}
				seriesLen = 1;
				prevColor = color;
			}
		}
	}
	
	public void finish() {
		while(!buffer.isEmpty()){
			rlepcx();
		}	
	}
	public int[] getRevMap(){
		int[] revMap = new int[256];
		for(int i=0;i<map.length;i++){
			revMap[getMapValue(i)] = i;
		}
		return revMap;
	}
}
